/*
 * The MIT License
 *
 * Copyright 2011 Roman Yakovenko <erelus@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.stego.transform;

import com.stego.image.Pixel;

/**
 * @author Roman Yakovenko <erelus@gmail.com>
 */
public class Wavelet {

    public Pixel[][] getLittleCopy(Pixel[][] data) {

        int width = data.length;
        int height = data[0].length;

        Pixel[][] copy = new Pixel[width / 2][height / 2];
        for (int i = 0; i < copy.length; i++) {
            for (int j = 0; j < copy[i].length; j++) {
                copy[i][j] = new Pixel();
            }
        }

        for (int i = 0; i < width / 2; i++) {
            for (int j = 0; j < height / 2; j++) {
                int red = (data[2 * i][2 * j].getRed()
                        + data[2 * i + 1][2 * j].getRed()
                        + data[2 * i][2 * j + 1].getRed()
                        + data[2 * i + 1][2 * j + 1].getRed()) / 4;
                copy[i][j].setRed(red);

                int green = (data[2 * i][2 * j].getGreen()
                        + data[2 * i + 1][2 * j].getGreen()
                        + data[2 * i][2 * j + 1].getGreen()
                        + data[2 * i + 1][2 * j + 1].getGreen()) / 4;
                copy[i][j].setGreen(green);

                int blue = (data[2 * i][2 * j].getBlue()
                        + data[2 * i + 1][2 * j].getBlue()
                        + data[2 * i][2 * j + 1].getBlue()
                        + data[2 * i + 1][2 * j + 1].getBlue()) / 4;
                copy[i][j].setBlue(blue);
            }
        }

        return copy;
    }

    public Pixel[][] getColsTransform(Pixel[][] data) {
        int width = data.length;
        int height = data[0].length;
        Pixel[][] transformed = new Pixel[width / 2][height / 2];
        for (int i = 0; i < transformed.length; i++) {
            for (int j = 0; j < transformed[i].length; j++) {
                transformed[i][j] = new Pixel();
            }
        }

        for (int i = 0; i < width / 2; i++) {
            for (int j = 0; j < height / 2; j++) {
                int red = (data[2 * i][2 * j].getRed()
                        + data[2 * i + 1][2 * j].getRed()
                        - data[2 * i][2 * j + 1].getRed()
                        - data[2 * i + 1][2 * j + 1].getRed()) / 4;
                transformed[i][j].setRed(red);

                int green = (data[2 * i][2 * j].getGreen()
                        + data[2 * i + 1][2 * j].getGreen()
                        - data[2 * i][2 * j + 1].getGreen()
                        - data[2 * i + 1][2 * j + 1].getGreen()) / 4;
                transformed[i][j].setGreen(green);

                int blue = (data[2 * i][2 * j].getBlue()
                        + data[2 * i + 1][2 * j].getBlue()
                        - data[2 * i][2 * j + 1].getBlue()
                        - data[2 * i + 1][2 * j + 1].getBlue()) / 4;
                transformed[i][j].setBlue(blue);
            }
        }
        return transformed;
    }

    public Pixel[][] getRowsTransform(Pixel[][] data) {

        int width = data.length;
        int height = data[0].length;
        Pixel[][] transformed = new Pixel[width / 2][height / 2];
        for (int i = 0; i < transformed.length; i++) {
            for (int j = 0; j < transformed[i].length; j++) {
                transformed[i][j] = new Pixel();
            }
        }

        for (int i = 0; i < width / 2; i++) {
            for (int j = 0; j < height / 2; j++) {

                int red = (data[2 * i][2 * j].getRed()
                        - data[2 * i + 1][2 * j].getRed()
                        + data[2 * i][2 * j + 1].getRed()
                        - data[2 * i + 1][2 * j + 1].getRed()) / 4;
                transformed[i][j].setRed(red);

                int green = (data[2 * i][2 * j].getGreen()
                        - data[2 * i + 1][2 * j].getGreen()
                        + data[2 * i][2 * j + 1].getGreen()
                        - data[2 * i + 1][2 * j + 1].getGreen()) / 4;
                transformed[i][j].setGreen(green);

                int blue = (data[2 * i][2 * j].getBlue()
                        - data[2 * i + 1][2 * j].getBlue()
                        + data[2 * i][2 * j + 1].getBlue()
                        - data[2 * i + 1][2 * j + 1].getBlue()) / 4;
                transformed[i][j].setBlue(blue);
            }
        }
        return transformed;

    }

    public Pixel[][] getDiagonalsTransform(Pixel[][] data) {

        int width = data.length;
        int height = data[0].length;
        Pixel[][] transformed = new Pixel[width / 2][height / 2];
        for (int i = 0; i < transformed.length; i++) {
            for (int j = 0; j < transformed[i].length; j++) {
                transformed[i][j] = new Pixel();
            }
        }

        for (int i = 0; i < width / 2; i++) {
            for (int j = 0; j < height / 2; j++) {

                int red = (data[2 * i][2 * j].getRed()
                        - data[2 * i + 1][2 * j].getRed()
                        - data[2 * i][2 * j + 1].getRed()
                        + data[2 * i + 1][2 * j + 1].getRed()) / 4;
                transformed[i][j].setRed(red);

                int green = (data[2 * i][2 * j].getGreen()
                        - data[2 * i + 1][2 * j].getGreen()
                        - data[2 * i][2 * j + 1].getGreen()
                        + data[2 * i + 1][2 * j + 1].getGreen()) / 4;
                transformed[i][j].setGreen(green);

                int blue = (data[2 * i][2 * j].getBlue()
                        - data[2 * i + 1][2 * j].getBlue()
                        - data[2 * i][2 * j + 1].getBlue()
                        + data[2 * i + 1][2 * j + 1].getBlue()) / 4;
                transformed[i][j].setBlue(blue);
            }
        }
        return transformed;

    }

    public Pixel[][] getInversedTransform(Pixel[][] small, Pixel[][] rows,
                                          Pixel[][] cols, Pixel[][] diags) {

        assert (small.length == rows.length);
        assert (rows.length == cols.length);
        assert (cols.length == diags.length);

        int width = small.length * 2;
        int height = small[0].length * 2;
        Pixel[][] result = new Pixel[width][height];
        for (int i = 0; i < result.length; i++) {
            for (int j = 0; j < result[i].length; j++) {
                result[i][j] = new Pixel();
            }
        }

        for (int i = 0; i < width / 2; i++) {
            for (int j = 0; j < height / 2; j++) {
                Pixel B4 = diags[i][j];
                Pixel B3 = rows[i][j];
                Pixel B2 = cols[i][j];
                Pixel B1 = small[i][j];

                int red = (B4.getRed() - B2.getRed() - B3.getRed() + B1.getRed());
                result[2 * i + 1][2 * j + 1].setRed(red);
                int green = B4.getGreen() - B2.getGreen() - B3.getGreen() + B1.getGreen();
                result[2 * i + 1][2 * j + 1].setGreen(green);
                int blue = B4.getBlue() - B2.getBlue() - B3.getBlue() + B1.getBlue();
                result[2 * i + 1][2 * j + 1].setBlue(blue);

                red = B1.getRed() - B4.getRed() - B2.getRed() + B3.getRed();
                result[2 * i][2 * j + 1].setRed(red);
                green = B1.getGreen() - B4.getGreen() - B2.getGreen() + B3.getGreen();
                result[2 * i][2 * j + 1].setGreen(green);
                blue = B1.getBlue() - B4.getBlue() - B2.getBlue() + B3.getBlue();
                result[2 * i][2 * j + 1].setBlue(blue);

                red = B1.getRed() + B2.getRed() - B3.getRed() - B4.getRed();
                result[2 * i + 1][2 * j].setRed(red);
                green = B1.getGreen() + B2.getGreen() - B3.getGreen() - B4.getGreen();
                result[2 * i + 1][2 * j].setGreen(green);
                blue = B1.getBlue() + B2.getBlue() - B3.getBlue() - B4.getBlue();
                result[2 * i + 1][2 * j].setBlue(blue);

                red = B1.getRed() + B2.getRed() + B3.getRed() + B4.getRed();
                result[2 * i][2 * j].setRed(red);
                green = B1.getGreen() + B2.getGreen() + B3.getGreen() + B4.getGreen();
                result[2 * i][2 * j].setGreen(green);
                blue = B1.getBlue() + B2.getBlue() + B3.getBlue() + B4.getBlue();
                result[2 * i][2 * j].setBlue(blue);
            }
        }
        return result;
    }
}
